﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace Supersalud.SJC.Datos
{
    public class ConexionSQL
    {
         #region Propiedades Privadas

        //Represents a sql-transact instruction in the sql server data base
        private SqlCommand _comando = null;

        private bool _esTransaccion { get; set; }

        //Represents a connection to sql server data base
        private SqlConnection _conexion { get; set; }

        //Represents a transaction to sql server data base
        private SqlTransaction _transaccion { get; set; }

        //provides a way to read a data stream
        private SqlDataReader _reader { get; set; }
        #endregion
        #region Propiedades publicas
        public TipoErrorSql TipoError { get; set; }
        public string Error { get; set; }
        
        #endregion



        public ConexionSQL()
        {
            _conexion = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SJCConnectionString"].ConnectionString);
        }

        protected void CrearComando(string consulta)
        {
            CrearComando(consulta, true);
        }

        protected void CrearComando(string consulta, bool esProcedimiento)
        {
            TipoError = TipoErrorSql.None;
            _comando = new SqlCommand()
            {
                CommandText = consulta,
                CommandType = esProcedimiento ? CommandType.StoredProcedure : CommandType.Text,
                CommandTimeout = _conexion.ConnectionTimeout,
                Connection = _conexion
            };

            if (_esTransaccion)
            {
                AbrirConexion();
                if (_transaccion == null)
                    _transaccion = _conexion.BeginTransaction(IsolationLevel.ReadCommitted);

                _comando.Transaction = _transaccion;
            }
        }

        protected void AgregarParametro(string nombre, object valor, ParameterDirection direccion, DbType tipo)
        {
            _comando.Parameters.Add(new SqlParameter()
            {
                DbType = tipo,
                Direction = direccion,
                ParameterName = nombre,
                Value = valor
            });
        }

        protected IDataRecord GetDataReader()
        {
            return _reader;
        }

        protected int EjecutarSinConsulta()
        {
            try
            {
                AbrirConexion();
                return _comando.ExecuteNonQuery();
            }
            catch (SqlException ex)
            {
                if (ex.Number == 2627)
                {
                    TipoError = TipoErrorSql.Unique;
                    return 0;
                }
                else if (ex.Number == 547)
                {
                    TipoError = TipoErrorSql.ReferenceConstraint;
                    Error = ex.ToString();
                    return 0;
                }
                else
                {
                    throw ex;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_esTransaccion)
                    CerrarConexion();
            }
        }

        protected object EjecutarEscalar()
        {
            try
            {
                AbrirConexion();
                return _comando.ExecuteScalar();
            }
            catch (SqlException ex)
            {
                if (ex.Number == 2627)
                {
                    TipoError = TipoErrorSql.Unique;
                    return 0;
                }
                else
                {
                    throw ex;
                }
            }
            finally
            {
                if (_esTransaccion)
                    CerrarConexion();
            }
        }

        protected void EjecutarConsulta()
        {
            try
            {
                AbrirConexion();
                if (_esTransaccion)
                {
                    _reader = _comando.ExecuteReader();
                }
                else
                {
                    _reader = _comando.ExecuteReader(CommandBehavior.CloseConnection);
                }
            }
            catch (Exception ex)
            {
                CerrarConexion();
                throw ex;
            }
        }

        protected bool Leer()
        {
            if (_reader.Read())
            {
                return true;
            }
            else
            {
                if (!_esTransaccion)
                {
                    CerrarConexion();
                }
            }
            return false;
        }

        protected void EnviarTransaccion()
        {
            if (_transaccion != null)
                _transaccion.Commit();
        }

        protected void DevolverTransaccion()
        {
            if (_transaccion != null)
                _transaccion.Rollback();
        }

        private void AbrirConexion()
        {
            if (_conexion.State != ConnectionState.Open)
                _conexion.Open();
        }

        private void CerrarConexion()
        {
            if (_conexion != null)
                _conexion.Close();
        }

        //void Grouptransaction(params ConexionSql<T>[] objects)
        //{
        //    _esTransaccion = true;
        //    AbrirConexion();
        //    _transaccion = _conexion.BeginTransaction(IsolationLevel.ReadCommitted);

        //    foreach (ConexionSql<T> item in objects)
        //    {
        //        item._esTransaccion = true;
        //        item._conexion = _conexion;
        //        item._transaccion = _transaccion;
        //    }
        //}


        #region GetValue
        public object GetValue(string name)
        {
            return _reader[name];
        }

        public object GetValue(int index)
        {
            return _reader[index];
        }

        public int GetIntValue(string name)
        {
            return Convert.ToInt32(_reader[name]);
        }

        public string GetStringValue(string name)
        {
            return _reader[name].ToString();
        }

        public bool GetBooleanValue(string name)
        {
            return Convert.ToBoolean(_reader[name]);
        }

        public DateTime GetDateValue(string name)
        {
            return Convert.ToDateTime(_reader[name]);
        }
        #endregion

        //protected void CargarParametros(string procedimiento)
        //{
        //    CrearComando(procedimiento, true);


        //    foreach (PropertyInfo item in typeof(T).GetProperties())
        //    {
        //        TipoDatoSql db = (Attribute.GetCustomAttribute(item, typeof(TipoDatoSql)) as TipoDatoSql);

        //        if (item.GetValue(Objeto, null) == null)
        //        {
        //            AgregarParametro(db.Nombre, item.GetValue(Objeto, null), ParameterDirection.Input, db.Tipo);
        //        }
        //    }
        //}

    }
    
    public enum TipoErrorSql
    {
        None,
        Unique,
        ReferenceConstraint
    }
}
